<?php
/**
 * @author		João Batista Neto
 * @brief		Objetos que trabalham com requisição e retorno da API BuscaPé
 * @package		dso.buscape.result
 */

require_once 'dso/buscape/result/BuscapeComponent.php';

/**
 * @brief		Resultados de uma consulta à API BuscaPé
 * @class		BuscapeResult
 * @ingroup		API
 */
class BuscapeResult extends BuscapeComponent {
	/**
	 * @brief	Lista de categorias
	 * @var		RecursiveComponentIterator
	 */
	private $categories;

	/**
	 * @brief	Tipo da pesquisa por palavra-chave
	 * @var		string
	 */
	private $match;

	/**
	 * @brief	Página atual
	 * @var		integer
	 */
	private $page;

	/**
	 * @brief	Lista de produtos
	 * @var		RecursiveComponentIterator
	 */
	private $products;

	/**
	 * @brief	Detalhes do resultado
	 * @var		BuscapeResultDetails
	 */
	private $resultDetails;

	/**
	 * @brief	Detalhes do vendedor
	 * @var		BuscapeSeller
	 */
	private $seller;

	/**
	 * @brief	Total de resultados retornados
	 * @var		integer
	 */
	private $totalResultsReturned;

	/**
	 * @brief	Total de resultados disponíveis
	 * @var		integer
	 */
	private $totalResultsAvailable;

	/**
	 * @brief	Total de páginas
	 * @var		integer
	 */
	private $totalPages;

	/**
	 * @brief	Verifica se um objeto é aceitável para o componente antes de adicioná-lo
	 * @param	$child BuscapeComponent
	 * @return	boolean
	 */
	protected function accept( IObject $child ){
		if ( parent::accept( $child ) ){
			return $child->getClass()->isSubclassOf( 'BuscapeType' );
		}

		return false;
	}

	/**
	 * @brief	Adiciona uma categoria à lista de resultados
	 * @param	$category BuscapeCategory A categoria que será adicionada
	 * @return	BuscapeResult Este objeto
	 */
	public function addCategory( BuscapeCategory $category ){
		if ( is_null( $this->categories ) ){
			$this->categories = new RecursiveComponentIterator();
		}

		$this->categories->append( $category );
		$this->add( $category );

		return $this;
	}

	/**
	 * @brief	Adiciona um novo produto à lista de resultados
	 * @param	$product BuscapeProduct O produto que será adicionado
	 * @return	BuscapeResult Este objeto
	 */
	public function addProduct( BuscapeProduct $product ){
		if ( is_null( $this->products ) ){
			$this->products = new RecursiveComponentIterator();
		}

		$this->products->append( $product );
		$this->add( $product );

		return $this;
	}

	/**
	 * @brief	Cria uma instância de BuscapeResult
	 * @param	$args array Argumentos utilizados para criação do objeto
	 * @return	BuscapeResult
	 */
	public static function createInstance( array $args ){
		$result = new BuscapeResult();

		foreach ( $args as $property => $value ){
			$result->$property = $value;
		}

		return $result;
	}

	/**
	 * @brief	Recupera um Iterator para as categorias do resultado
	 * @param	$recursive boolean Indica se o Iterator deve ser recursivo
	 * @return	RecursiveComponentIterator
	 * @see		BuscapeResult.addCategory()
	 * @throws	BadMethodCallException Se nenhuma categoria tiver sido adicionada
	 */
	public function getCategories( $recursive = false ){
		if ( !is_null( $this->categories ) ){
			if ( $recursive ){
				$iterator = new RecursiveComponentIteratorIterator( $this->categories );
			} else {
				$iterator = $this->categories;
			}
		} else {
			throw new BadMethodCallException( 'Nenhuma categoria para retornar' );
		}

		return $iterator;
	}

	/**
	 * @brief	Recupera um Iterator para os produtos do resultado
	 * @param	$recursive boolean Indica se o Iterator deve ser recursivo
	 * @return	RecursiveComponentIterator
	 * @see		BuscapeResult.addProduct()
	 * @throws	BadMethodCallException Se nenhum produto tiver sido adicionado
	 */
	public function getProducts( $recursive = false ){
		if ( !is_null( $this->products ) ){
			if ( $recursive ){
				$iterator = new RecursiveComponentIteratorIterator( $this->products );
			} else {
				$iterator = $this->products;
			}
		} else {
			throw new BadMethodCallException( 'Nenhum produto para retornar' );
		}

		return $iterator;
	}

	/**
	 * @return string
	 */
	public function getMatch() {
		return $this->match;
	}

	/**
	 * @brief	Recupera a página atual
	 * @return	integer
	 */
	public function getPage() {
		return $this->page;
	}

	/**
	 * @brief	Recupera o total de resultados retornados
	 * @return	integer
	 */
	public function getTotalResultsReturned() {
		return $this->totalResultsReturned;
	}

	/**
	 * @brief	Recupera o total de resultados disponíveis
	 * @return	integer
	 */
	public function getTotalResultsAvailable() {
		return $this->totalResultsAvailable;
	}

	/**
	 * @brief	Recupera o total de páginas
	 * @return	integer
	 */
	public function getTotalPages() {
		return $this->totalPages;
	}

	/**
	 * @brief	Recupera os detalhes do vendedor
	 * @return	BuscapeSeller
	 */
	public function getSeller(){
		return $this->seller;
	}

	/**
	 * @brief	Verifica se o tipo é uma folha
	 * @return	boolean
	 * @see		BuscapeComponent.isLeaf(), BuscapeCategory.isFinal()
	 */
	protected function isLeaf(){
		return false;
	}

	/**
	 * @brief	Define os detalhes do resultado
	 * @param	$resultDetails BuscapeResultDetails
	 */
	public function setResultDetails( BuscapeResultDetails $resultDetails ){
		$this->resultDetails = $resultDetails;
		$this->add( $resultDetails );
	}
}